package tech.xs.sys.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import tech.xs.auth.api.AuthTokenApi;
import tech.xs.auth.api.AuthUserPasswordApi;
import tech.xs.auth.api.domain.bo.password.ResetDefaultPasswordBo;
import tech.xs.auth.api.domain.bo.token.UpdateTokenBo;
import tech.xs.common.auth.domain.enums.AuthPathWhiteTypeEnum;
import tech.xs.common.framework.domain.annotations.AuthApi;
import tech.xs.common.sys.domain.bo.CurrLoginUserBo;
import tech.xs.common.sys.domain.bo.UserDetailsBo;
import tech.xs.common.framework.domain.entity.BaseEntity;
import tech.xs.common.framework.domain.model.ApiResult;
import tech.xs.common.framework.domain.model.PageResult;
import tech.xs.common.framework.util.AuthUtil;
import tech.xs.common.sys.domain.constant.PermissionConstant;
import tech.xs.common.sys.domain.enums.SysAccountStatusEnum;
import tech.xs.sys.domain.bo.user.EditUserBo;
import tech.xs.sys.domain.bo.user.PageUserBo;
import tech.xs.sys.domain.bo.user.UpdateCurrBo;
import tech.xs.sys.domain.entity.SysUser;
import tech.xs.sys.domain.entity.SysUserRole;
import tech.xs.sys.service.SysUserRoleService;
import tech.xs.sys.service.SysUserService;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.io.IOException;

/**
 * @author 沈家文
 * @since 2023/6/8 17:08
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/user")
public class SysUserController {

    @Resource
    private SysUserService sysUserService;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private AuthTokenApi authTokenApi;

    @Resource
    private AuthUserPasswordApi authUserPasswordApi;

    /**
     * 根据用户id获取用户信息
     *
     * @param userId 用户id
     * @return 响应数据
     * @author 沈家文
     * @since 2023/6/6 11:24
     */
    @GetMapping("/getUserDetails")
    public ApiResult<UserDetailsBo> getUserDetails(@RequestParam("userId") Long userId) {
        return ApiResult.success(sysUserService.getUserDetails(userId));
    }

    /**
     * 根据用户名获取用户信息
     *
     * @return 响应数据
     * @author 沈家文
     * @since 2023/6/6 11:24
     */
    @GetMapping("/curr")
    @AuthApi(type = AuthPathWhiteTypeEnum.LOGIN)
    public ApiResult<UserDetailsBo> getCurrUser() {
        CurrLoginUserBo currLoginUser = AuthUtil.getCurrLoginUser();
        return ApiResult.success(sysUserService.getUserDetails(currLoginUser.getUserId()));
    }

    @GetMapping("/list/page")
    @AuthApi(permissions = PermissionConstant.USER_QUERY)
    public PageResult<SysUser> page(@ModelAttribute PageUserBo bo) {
        return PageResult.success(sysUserService.page(bo.page(), bo.query()));
    }

    /**
     * 根据id更新或保存用户信息
     *
     * @param bo 请求参数
     * @return 响应数据
     * @author 沈家文
     * @since 2023/6/21 16:10
     */
    @PostMapping("/saveOrUpdate/manual")
    @AuthApi(permissions = PermissionConstant.USER_EDIT)
    public ApiResult<SysUser> manualEdit(@Validated @RequestBody EditUserBo bo) {
        bo.checkParameter();
        String userName = bo.getUserName();

        long existCount = sysUserService.count(Wrappers.<SysUser>lambdaQuery()
                .eq(SysUser::getUserName, bo.getUserName())
                .ne(bo.getId() != null, BaseEntity::getId, bo.getId()));
        if (existCount > 0) {
            return ApiResult.error("用户名已经存在");
        }

        SysUser saveData = new SysUser();
        BeanUtil.copyProperties(bo, saveData);
        boolean isUpdate = false;
        if (bo.getId() != null) {
            SysUser dbData = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery().eq(BaseEntity::getId, bo.getId()));
            if (dbData == null) {
                return ApiResult.error("根据id在系统中未查询到数据");
            }
            if (StrUtil.isNotBlank(userName) && sysUserRoleService.count(Wrappers.<SysUserRole>lambdaQuery().eq(SysUserRole::getUserName, userName)) > 0) {
                return ApiResult.error("用户名已经被使用,不允许修改");
            }
            isUpdate = true;
        }

        log.info("手动更新或保存用户:" + saveData);
        if (isUpdate) {
            sysUserService.updateById(saveData);
            UpdateTokenBo updateTokenBo = new UpdateTokenBo();
            updateTokenBo.setUserId(saveData.getId());
            sysUserService.deleteUserDetailsCache(saveData.getId());
            authTokenApi.updateToken(updateTokenBo);
        } else {
            sysUserService.save(saveData);
            ResetDefaultPasswordBo resetDefaultPasswordBo = new ResetDefaultPasswordBo();
            resetDefaultPasswordBo.setUserName(saveData.getUserName());
            authUserPasswordApi.resetDefaultPassword(resetDefaultPasswordBo);
        }
        return ApiResult.success(saveData);
    }

    /**
     * 当前用户修改自身用户信息
     */
    @PostMapping("/update/curr")
    @AuthApi(type = AuthPathWhiteTypeEnum.LOGIN)
    public ApiResult<Void> updateCurr(@RequestBody UpdateCurrBo bo) {
        CurrLoginUserBo currLoginUser = AuthUtil.getCurrLoginUser();
        SysUser dbData = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery().eq(BaseEntity::getId, currLoginUser.getUserId()));
        if (!SysAccountStatusEnum.NORMAL.equals(dbData.getAccountStatus())) {
            return ApiResult.error("用户状态错误");
        }
        SysUser updateUser = new SysUser();
        BeanUtil.copyProperties(bo, updateUser);
        updateUser.setId(dbData.getId());
        sysUserService.updateById(updateUser);
        UpdateTokenBo updateTokenBo = new UpdateTokenBo();
        updateTokenBo.setUserId(dbData.getId());
        sysUserService.deleteUserDetailsCache(dbData.getId());
        authTokenApi.updateToken(updateTokenBo);
        return ApiResult.success();
    }


    /**
     * 徐工当前登陆用户头像
     */
    @AuthApi(type = AuthPathWhiteTypeEnum.LOGIN)
    @PostMapping("/curr/updateUserAvatar")
    public ApiResult<String> updateCurrUserAvatar(@NotNull @RequestParam("avatar") MultipartFile avatar) throws IOException {
        if (avatar.isEmpty()) {
            return ApiResult.invalidParameter("avatar");
        }
        return ApiResult.success(sysUserService.updateCurrUserAvatar(avatar));
    }


}
